﻿//------------------------------------------------------------------------------
//  Namespace: FruitVentDesign.Utils
//  
//  Function： N/A
//  Name： FrontEndUtils
//  
//  Ver       Time                     Author
//  0.10      2021/6/17 10:16:32      FruitVent
//
//  此代码版权归作者本人FruitVent所有
//  源代码使用协议遵循本仓库的开源协议及附加协议，若本仓库没有设置，则按MIT开源协议授权
//  CSDN博客：https://blog.csdn.net/weixin_39552347
//  源代码仓库：https://gitee.com/fruitvent
//  感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using FruitVentDesign.Models;
using FruitVentDesign.UtilWindows;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace FruitVentDesign.Utils
{
    public static class FrontEndUtils
    {
        private static void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Window window = sender as Window;
            if (window.Owner != null)
            {
                _ = window.Owner.Activate();
            }
        }

        private static readonly ResourceDictionary resourceDictionary =
            new ResourceDictionary()
            {
                Source = new Uri(
               $"pack://application:,,,/FruitVentDesign;component/Styles/Window/" +
               $"Windows.xaml")
            };//资源字典

        public static void ReportMessage(string message, Window win = null)
        {
            Application.Current.Dispatcher.Invoke(
                () =>
                {
                    AlertWindow window = new AlertWindow(message) { Title = "提示" };
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    window.Closing += Window_Closing;
                    _ = window.ShowDialog();
                });
        }

        public static void ReportError(string stage, Exception error, Window win = null)
        {
            //logger.Error(error, $"{stage}时发生错误");

            Application.Current.Dispatcher.Invoke(
                () =>
                {
                    string message = $"{stage}时发生错误: {error.Message}";
                    ReadOnlyWindow window = new ReadOnlyWindow(message) { Title = "错误", Style = resourceDictionary["WindowStyle.Red"] as Style };
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    window.Closing += Window_Closing;
                    _ = window.ShowDialog();
                });
        }

        /// <summary>
        /// show a dialog to ask user's confirmation
        /// </summary>
        /// <param name="message"></param>
        /// <param name="win"></param>
        /// <returns>if user confirm return true, else return false. </returns>
        public static bool ConfirmOperation(string message, Window win = null)
        {
            return Application.Current.Dispatcher.Invoke(
                () =>
                {
                    ConfirmWindow window = new ConfirmWindow(message) { Title = "确认" };
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    window.Closing += Window_Closing;
                    return window.ShowDialog() is true;
                });
        }

        /// <summary>
        /// show a dialog to ask user to enter a message.
        /// </summary>
        /// <param name="win"></param>
        /// <returns>return null if cancel entering, else return a text.</returns>
        public static string AskforEnter(Window win = null)
        {
            return Application.Current.Dispatcher.Invoke(
                () =>
                {
                    EnterWindow window = new EnterWindow
                    {
                        Title = "输入"
                    };
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    window.Closing += Window_Closing;
                    return window.ShowDialog() is true ? window.Text : null;
                });
        }

        /// <summary>
        /// notice message
        /// </summary>
        /// <param name="message"></param>
        public static void NoticeMessage(string message)
        {
            Application.Current.Dispatcher.Invoke(
                () =>
                {
                    NoticeWindow noticeWindow = new NoticeWindow(message) { Title = "消息通知" };
                    noticeWindow.Left = SystemParameters.WorkArea.Width - noticeWindow.ActualWidth;
                    noticeWindow.Top = SystemParameters.WorkArea.Height - noticeWindow.ActualHeight;
                    noticeWindow.Closing += Window_Closing;
                    noticeWindow.Show();
                });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="win"></param>
        public static void PopupMessage(string message, Window win = null)
        {
            Application.Current.Dispatcher.Invoke(
                () =>
                {
                    PopupWindow window = new PopupWindow(message, durationSec: 0.6, fadeSec: 0.3);
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    // window.Closing += Window_Closing;
                    window.Show();
                });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="win"></param>
        public static void ReportReadOnlyMessage(string message, Window win = null)
        {
            Application.Current.Dispatcher.Invoke(
                () =>
                {
                    ReadOnlyWindow window = new ReadOnlyWindow(message) { Title = "提示" };
                    if (win != null)
                    {
                        window.Owner = win;
                        window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    }
                    else
                    {
                        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    }
                    window.Closing += Window_Closing;
                    _ = window.ShowDialog();
                });
        }

        public static void WaitingOperation(string operationName, Action action, bool inSTA = false, Window win = null)
        {
            WaitingWindow window = new WaitingWindow();
            if (win != null)
            {
                window.Owner = win;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
            window.Closing += Window_Closing;
            bool? result = window.WaitingFor(action, inSTA);
            if (window.HasException)
            {
                ReportError(operationName, window.Exception);
            }
        }

        public static void WaitingOperation(string operationName, Action<EventHandler<ReportEventArgs>> action, bool inSTA = false, Window win = null)
        {
            WaitingWindow window = new WaitingWindow();
            if (win != null)
            {
                window.Owner = win;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
            window.Closing += Window_Closing;
            bool? result = window.WaitingFor(action, inSTA);
            if (window.HasException)
            {
                ReportError(operationName, window.Exception);
            }
        }

        public static T WaitingOperation<T>(string operationName, Func<T> func, bool inSTA = false, Window win = null)
        {
            WaitingWindow window = new WaitingWindow();
            if (win != null)
            {
                window.Owner = win;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
            window.Closing += Window_Closing;
            bool? result = window.WaitingFor(func, inSTA);
            if (result is true)
            {
                return (T)window.Result;
            }
            else
            {
                if (window.HasException) { ReportError(operationName, window.Exception); }
                return default(T);
            }
        }

        public static T WaitingOperation<T>(string operationName, Func<EventHandler<ReportEventArgs>, T> func, bool inSTA = false, Window win = null)
        {
            WaitingWindow window = new WaitingWindow();
            if (win != null)
            {
                window.Owner = win;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
            window.Closing += Window_Closing;
            bool? result = window.WaitingFor(func, inSTA);
            if (result is true)
            {
                return (T)window.Result;
            }
            else
            {
                if (window.HasException) { ReportError(operationName, window.Exception); }
                return default(T);
            }
        }


        /// <summary>
        /// 提示一下
        /// </summary>
        /// <param name="message">提示消息</param>
        /// <param name="duration">等待时长</param>
        public static async Task TipAsync(this string message, int duration = 1000)
        {
            Window win = Application.Current.Windows.Cast<Window>().ToList().Find(o => o.IsActive);
            if(win != null)
            {
                Visual visual = (Visual)win.Template.FindName("Window_Content", win);
                //获取visual上面的第一个AdornerLayer
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(visual);
                //创建我们定义的Adorner
                var _adorner = new SimpleAdorner(adornerLayer)
                {
                    //添加一个半透明的Border
                    Child = new Tip(message)
                };

                //添加到adornerLayer装饰层上
                adornerLayer.Add(_adorner);
                //等待1秒,模拟耗时操作
                await Task.Delay(duration);
                //移除
                adornerLayer.Remove(_adorner);
            }
        }
    }
}
